"""
计分方式：共30个条目。其中，条目29、30分为七个等级，根据其回答选项，计为1分到7分；
其它条目分为4个等级：从没有、有一点、较多至很多，评分时，直接评1到4分。
将各个领域所包括的条目得分相加并除以所包括的条目数即可得到该领域的得分
为了使得各领域得分能相互比较，还进一步采用极差化方法进行线性变换，
将粗分转化为在O～100内取值的标准化得分(standard score，SS)。
此外，变换还有一个目的，即改变得分的方向。因为QLQ—C30量表，除条目29、3O外均为逆向条目(取值越大，生命质量越差)，
而在计分规则中明确规定：对于功能领域和总体健康状况领域得分越高说明功能状况和生命质量越好，对于症状领域得分越高表明症状或问题越多(生命质量越差)。
因此，计算功能领域的标化分时还要改变方向。具体说来，分别按下式计算(式中R为各领域或条目的得分全距)。
功能领域：SS=[1一(RS一1)／R]×100
症状领域和总体健康状况领域：SS=[(RS一1)／R]×100

QLQ-C30(V3.0)各领域的计分方法(粗分RS):
躯体功能:功能型、条目5、得分全距3、计分方法（括号内代表题目号（1+2+3+4+5）/5
角色功能:功能型、条目2、得分全距3、计分方法（括号内代表题目号):（6+7）/5
情绪功能:功能型、条目4、得分全距3、计分方法（括号内代表题目号):（21+22+23+24）/4
认知功能:功能型、条目2、得分全距3、计分方法（括号内代表题目号):（20+25）/2
社会功能:功能型、条目2、得分全距3、计分方法（括号内代表题目号):（26+27）/2
总健康水平:条目2、得分全距6、计分方法（括号内代表题目号):（29+30）/2
疲倦:症状型、条目5、得分全距3、计分方法（括号内代表题目号):（10+12+18）/3
疲倦:症状型、条目3、得分全距3、计分方法（括号内代表题目号):（10+12+18）/3
恶心与呕吐:症状型、条目2、得分全距3、计分方法（括号内代表题目号):（14+15）/2
疼痛:症状型、条目2、得分全距3、计分方法（括号内代表题目号):（9+19）/2
气促:症状型、条目1、得分全距3、计分方法（括号内代表题目号):8
失眠:症状型、条目1、得分全距3、计分方法（括号内代表题目号):11
食欲丧失:症状型、条目1、得分全距3、计分方法（括号内代表题目号):13
便秘:症状型、条目1、得分全距3、计分方法（括号内代表题目号):16
腹泻:症状型、条目1、得分全距3、计分方法（括号内代表题目号):17
经济困难:症状型、条目1、得分全距3、计分方法（括号内代表题目号):28
"""
class QLQ_C30:
    def __init__(self, answers):
        self.answers = answers
        self.domain_scores = {
            'physical_functioning': [],
            'role_functioning': [],
            'emotional_functioning': [],
            'cognitive_functioning': [],
            'social_functioning': [],
            'global_health_status': [],
            'fatigue': [],
            'nausea_vomiting': [],
            'pain': [],
            'dyspnea': [],
            'insomnia': [],
            'appetite_loss': [],
            'constipation': [],
            'diarrhea': [],
            'financial_difficulties': []
        }
        self.standard_scores = {}

    def calculate_scores(self):
        self._assign_answers_to_domains()
        self._calculate_raw_scores()
        self._calculate_standard_scores()

    def _assign_answers_to_domains(self):
        # 根据条目分配答案到各个领域
        self.domain_scores['physical_functioning'] = [int(self.answers[f'q{i}']) for i in [1, 2, 3, 4, 5]]
        self.domain_scores['role_functioning'] = [int(self.answers[f'q{i}']) for i in [6, 7]]
        self.domain_scores['emotional_functioning'] = [int(self.answers[f'q{i}']) for i in [21, 22, 23, 24]]
        self.domain_scores['cognitive_functioning'] = [int(self.answers[f'q{i}']) for i in [20, 25]]
        self.domain_scores['social_functioning'] = [int(self.answers[f'q{i}']) for i in [26, 27]]
        self.domain_scores['global_health_status'] = [int(self.answers[f'q{i}']) for i in [29, 30]]
        self.domain_scores['fatigue'] = [int(self.answers[f'q{i}']) for i in [10, 12, 18]]
        self.domain_scores['nausea_vomiting'] = [int(self.answers[f'q{i}']) for i in [14, 15]]
        self.domain_scores['pain'] = [int(self.answers[f'q{i}']) for i in [9, 19]]
        self.domain_scores['dyspnea'] = [int(self.answers[f'q{8}'])]
        self.domain_scores['insomnia'] = [int(self.answers[f'q{11}'])]
        self.domain_scores['appetite_loss'] = [int(self.answers[f'q{13}'])]
        self.domain_scores['constipation'] = [int(self.answers[f'q{16}'])]
        self.domain_scores['diarrhea'] = [int(self.answers[f'q{17}'])]
        self.domain_scores['financial_difficulties'] = [int(self.answers[f'q{28}'])]

    def _calculate_raw_scores(self):
        for domain, scores in self.domain_scores.items():
            self.domain_scores[domain] = sum(scores) / len(scores)

    def _calculate_standard_scores(self):
        for domain, raw_score in self.domain_scores.items():
            if domain in ['physical_functioning', 'role_functioning', 'emotional_functioning', 'cognitive_functioning',
                          'social_functioning']:
                self.standard_scores[domain] = round((1 - (raw_score - 1) / 3) * 100, 1)
            elif domain == 'global_health_status':
                self.standard_scores[domain] = round((1 - (raw_score - 1) / 6) * 100, 1)
            else:
                self.standard_scores[domain] = round(((raw_score - 1) / 3) * 100, 1)

    def get_scores(self):
        return self.domain_scores, self.standard_scores

# # 示例使用
# answers = {
#     'q1': '3', 'q2': '2', 'q3': '1', 'q4': '4', 'q5': '3', 'q6': '2', 'q7': '1', 'q8': '4',
#     'q9': '3', 'q10': '2', 'q11': '1', 'q12': '4', 'q13': '3', 'q14': '2', 'q15': '1', 'q16': '4',
#     'q17': '3', 'q18': '2', 'q19': '1', 'q20': '4', 'q21': '3', 'q22': '2', 'q23': '1', 'q24': '4',
#     'q25': '3', 'q26': '2', 'q27': '1', 'q28': '4', 'q29': '3', 'q30': '2'
# }
#
# """
# 初始化：QLQ_C30 类接收一个包含用户回答的字典 answers。
# 分配答案到各个领域：_assign_answers_to_domains 方法将每个条目的答案分配到相应的领域，根据您提供的条目号。
# 计算原始得分：_calculate_raw_scores 方法计算每个领域的原始得分，即将该领域所有条目的得分相加并除以条目数。
# 计算标准化得分：_calculate_standard_scores 方法将原始得分转换为标准化得分（SS），并根据领域的不同进行方向调整。
# 获取得分：get_scores 方法返回原始得分和标准化得分。
# 示例使用：提供一个示例回答字典，并计算各个领域的原始得分和标准化得分。
# 通过这种方式，您可以在后端计算QLQ-C30的评分，并将其转换为标准化得分，以便进行比较和分析。
# """
# qlq_c30 = QLQ_C30(answers)
# qlq_c30.calculate_scores()
# domain_scores, standard_scores = qlq_c30.get_scores()
# print("Domain Scores:", domain_scores)
# print("Standard Scores:", standard_scores)